import * as Cesium from 'cesium'

export class LatLng {
  constructor(
    public lat: number,
    public lng: number,
    public height: number = 0,
  ) {}
}

/**
 * 添加地图图层
 * @param viewer
 * @param layer
 */
export function addLayer(viewer: Cesium.Viewer, layer: Cesium.ImageryLayer, alpha: number = 0.7) {
  layer.alpha = alpha
  viewer.imageryLayers.add(layer)
}

/**
 * 角度转弧度
 * @param angle
 * @returns
 */
export function angleToRadians(angle: number) {
  return Cesium.Math.toRadians(angle)
}

/**
 * 经纬度坐标转笛卡尔三维坐标
 * @param lat
 * @param lng
 * @param height
 * @returns
 */
export function latlngToCartographic(lat: number, lng: number, height: number = 0) {
  return Cesium.Cartesian3.fromDegrees(lng, lat, height)
}

/**
 * 笛卡尔坐标转经纬度坐标
 * @param cartographic
 * @returns
 */
export function cartographicToLatlng(cartographic: Cesium.Cartesian3) {
  var target = Cesium.Cartographic.fromCartesian(cartographic)
  return {
    lat: Cesium.Math.toDegrees(target.latitude),
    lng: Cesium.Math.toDegrees(target.longitude),
    height: target.height,
  }
}

/**
 * 设置相机位置
 * @param viewer
 * @param heading
 * @param pitch
 * @param roll
 * @param position
 */
export function setCameraView(
  viewer: Cesium.Viewer,
  position: LatLng,
  heading: number = 0,
  pitch: number = -90,
  roll: number = 0,
) {
  viewer.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(position.lng, position.lat, position.height),
    orientation: {
      heading: Cesium.Math.toRadians(heading),
      pitch: Cesium.Math.toRadians(pitch),
      roll: roll,
    },
  })
}

/**
 * 相机动画移动到指定位置
 * @param viewer
 * @param heading
 * @param pitch
 * @param roll
 * @param duration
 * @param position
 */
export function flyTo(
  viewer: Cesium.Viewer,
  position: LatLng,
  heading: number = 0,
  pitch: number = -90,
  roll: number = 0,
  duration: number = 2,
) {
  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(position.lng, position.lat, position.height),
    orientation: {
      heading: Cesium.Math.toRadians(heading),
      pitch: Cesium.Math.toRadians(pitch),
      roll: roll,
    },
    duration: duration,
  })
}

/**
 * 注册键盘事件
 * @param callback
 */
export function addKeydownEvent(callback: Function) {
  document.addEventListener('keydown', function (e) {
    callback(e)
  })
}

/**
 * 移除键盘事件
 * @param callback
 */
export function removeKeydownEvent(callback: Function) {
  document.removeEventListener('keydown', function (e) {
    callback(e)
  })
}

/**
 * 添加点击事件
 * @param viewer
 * @param callback
 */
export function addClickEvent(viewer: Cesium.Viewer, callback: Function) {
  viewer.container.addEventListener('click', function (e) {
    callback(e)
  })
}

/**
 * 移除点击事件
 * @param viewer
 * @param callback
 */
export function removeClickEvent(viewer: Cesium.Viewer, callback: Function) {
  viewer.container.removeEventListener('click', function (e) {
    callback(e)
  })
}

/**
 * 获取点击位置经纬度
 * @param x
 * @param y
 * @returns
 */
export function getClickPostionForLatLng(viewer: Cesium.Viewer, x: number, y: number) {
  const windowPosition = new Cesium.Cartesian2(x, y)

  let cartesian: Cesium.Cartesian3 | undefined = viewer.scene.pickPosition(windowPosition)
  if (Cesium.defined(cartesian)) {
    return cartographicToLatlng(cartesian)
  } else {
    // 使用射线与地形交点来获取海拔信息
    const ray = viewer.camera.getPickRay(windowPosition)
    if (ray) {
      cartesian = viewer.scene.globe.pick(ray, viewer.scene)
      if (Cesium.defined(cartesian)) {
        return cartographicToLatlng(cartesian)
      }
    }
    // 最后回退到椭球（仅在没有地形数据时使用）
    cartesian = viewer.camera.pickEllipsoid(windowPosition, viewer.scene.globe.ellipsoid)
    if (Cesium.defined(cartesian)) {
      return cartographicToLatlng(cartesian)
    }
  }
}

/**
 * 添加点
 * @param viewer
 * @param latlng
 * @param point
 * @returns
 */
export function addPoint(
  viewer: Cesium.Viewer,
  id: string,
  latlng: LatLng,
  point: Cesium.PointGraphics,
) {
  const entity = new Cesium.Entity({
    position: latlngToCartographic(latlng.lat, latlng.lng, latlng.height),
    point: point,
    id: id,
  })
  viewer.entities.add(entity)
  return entity
}

/**
 * 添加默认建筑
 * @param viewer
 */
export async function addDefaultBuilding(viewer: Cesium.Viewer) {
  const osmBuildings = await Cesium.createOsmBuildingsAsync()
  viewer.scene.primitives.add(osmBuildings)
}

/**
 * 添加标签
 * @param viewer
 * @param id
 * @param latlng
 * @param label
 * @param billboard
 * @returns
 */
export function addLabel(
  viewer: Cesium.Viewer,
  id: string,
  latlng: LatLng,
  label: Cesium.LabelGraphics,
  billboard: Cesium.BillboardGraphics | undefined = undefined,
) {
  let entity = viewer.entities.add({
    position: latlngToCartographic(latlng.lat, latlng.lng, latlng.height),
    label: label,
    id: id,
    billboard: billboard,
  })

  return entity
}

/**
 * 添加简易标签
 * @param viewer
 * @param id
 * @param latlng
 * @param text
 * @returns
 */
export function addSimpleLabel(viewer: Cesium.Viewer, id: string, latlng: LatLng, text: string) {
  var label = viewer.entities.add({
    position: latlngToCartographic(latlng.lat, latlng.lng, latlng.height),
    label: {
      text: text,
      font: '20px sans-serif',
      fillColor: Cesium.Color.WHITE,
      outlineColor: Cesium.Color.BLACK,
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      outlineWidth: 2,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
    },
    id: id,
  })
  return label
}

/**
 * 加载glb模型
 * @param viewer
 * @param id
 * @param latlng
 * @param glbPath
 */
export async function addGlbModel(
  viewer: Cesium.Viewer,
  id: string,
  latlng: LatLng,
  glbPath: string,
  zoomTo: boolean = false,
) {
  const model = viewer.entities.add({
    position: latlngToCartographic(latlng.lat, latlng.lng, latlng.height),
    model: {
      uri: glbPath,
      minimumPixelSize: 128,
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000),
      silhouetteColor: Cesium.Color.WHITE,
      silhouetteSize: 1,
    },
    id: id,
  })
  if (zoomTo) {
    //缩放到模型所在的位置
    // await viewer.zoomTo(model)
    viewer.flyTo(model, {
      duration: 2,
      offset: new Cesium.HeadingPitchRange(0, -0.5, 200), //这里设置俯仰角和距离
    })
  }
  return model
}

// export function addRectangle(
//   viewer: Cesium.Viewer,
//   id: string,
//   start: LatLng,
//   end: LatLng,
//   zoomTo: boolean = false,
// ) {
//   //创建实例
//   const instance = new Cesium.GeometryInstance({
//     geometry: new Cesium.RectangleGeometry({
//       rectangle: Cesium.Rectangle.fromDegrees(start.lng, start.lat, end.lng, end.lat),
//       height: 10, // 或者移除这行以贴地显示
//     }),
//     attributes: {
//       color: Cesium.ColorGeometryInstanceAttribute.fromColor(
//         Cesium.Color.fromRandom({ alpha: 0.5 }),
//       ),
//     },
//     id: id,
//   })
//   //创建外观
//   const appearance = new Cesium.EllipsoidSurfaceAppearance({
//     material: Cesium.Material.fromType('Color', {
//       color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),
//     }),
//   })
//   // 3. 创建Primitive
//   const primitive = new Cesium.Primitive({
//     geometryInstances: instance,
//     appearance: appearance,
//     asynchronous: false, // 是否异步加载
//   })
//   viewer.scene.primitives.add(primitive)
//   return primitive
//   // if (zoomTo) {
//   //   const center = Cesium.Cartesian3.fromDegrees(
//   //     (start.lng + end.lng) / 2.0,
//   //     (start.lat + end.lat) / 2.0,
//   //     10,
//   //   )
//   //   viewer.camera.flyTo({
//   //     destination: center,
//   //     duration: 2,
//   //     orientation: {
//   //       heading: 0,
//   //       pitch: -0.5,
//   //       roll: 0,
//   //     },
//   //   })
//   // }
// }

/**
 * 添加矩形
 * @param viewer
 * @param id
 * @param southwest
 * @param northeast
 * @param height
 * @param extrudedHeight
 * @param zoomTo
 * @param color
 * @returns
 */
export function addRectangle(
  viewer: Cesium.Viewer,
  id: string,
  southwest: LatLng,
  northeast: LatLng,
  height: number = 0, //离地高度
  extrudedHeight: number = 0, //挤出高度
  zoomTo: boolean = false,
  color: Cesium.Color = Cesium.Color.RED.withAlpha(0.5),
) {
  // 创建几何实例
  const instance = new Cesium.GeometryInstance({
    geometry: new Cesium.RectangleGeometry({
      rectangle: Cesium.Rectangle.fromDegrees(
        southwest.lng,
        southwest.lat,
        northeast.lng,
        northeast.lat,
      ),
      height: height,
      extrudedHeight: extrudedHeight,
    }),
    attributes: {
      color: Cesium.ColorGeometryInstanceAttribute.fromColor(color),
    },
    id: id,
  })

  // 根据是否有高度选择不同的外观
  const appearance =
    height === 0
      ? new Cesium.EllipsoidSurfaceAppearance({
          material: Cesium.Material.fromType('Color', { color }),
        })
      : new Cesium.PerInstanceColorAppearance({
          flat: true,
          translucent: color.alpha < 1.0,
        })

  // 创建Primitive
  const primitive = new Cesium.Primitive({
    geometryInstances: instance,
    appearance: appearance,
    asynchronous: false,
  })

  // 添加到场景中
  viewer.scene.primitives.add(primitive)

  if (zoomTo) {
    const center = Cesium.Cartesian3.fromDegrees(
      (southwest.lng + northeast.lng) / 2.0,
      (southwest.lat + northeast.lat) / 2.0,
      1000,
    )
    viewer.camera.flyTo({
      destination: center,
      duration: 2,
      orientation: {
        heading: 0,
        pitch: -0.5,
        roll: 0,
      },
    })
  }
  return primitive
}
